﻿using Furion.FriendlyException;
using Furion.IPCChannel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FurStudy.Core
{
    /// <summary>
    /// 创建管道处理程序（处理String类型消息）
    /// </summary>
    public class MyChannelHandler : ChannelHandler<string> // ChannelHandler<TMessage>泛型类型决定了你要接收那种类型的消息，不同类型消息将会自动过滤筛选
    {
        /// <summary>
        /// 接收到管道消息后处理程序
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public override Task InvokeAsync(string message)
        {
            Console.WriteLine(message);

            return Task.CompletedTask;
        }

        /// <summary>
        /// 使用ChannelContext<TMessage, THandler>发送消息
        /// </summary>
        /// <returns></returns>
        public async Task Sendsync()
        {
            for (int i = 0; i < 100; i++)
            {
                // 使用有限容量生产数据
                await ChannelContext<string, MyChannelHandler>.BoundedChannel.Writer.WriteAsync($"Loop {i} times.");

                // 以上代码也可以通过以下方式同步写入
                // ChannelContext<string, MyChannelHandler>.BoundedChannel.Writer.TryWrite();
            }
        }

        /// <summary>
        /// 实现多订阅
        /// </summary>
        public void ImplementMultipleSubscriptionsDemo()
        {
            var reader = ChannelContext<string, MyChannelHandler>.BoundedChannel.Reader;

            // 创建长时间线程管道读取器
            _ = Task.Factory.StartNew(async () =>
            {
                while (await reader.WaitToReadAsync())
                {
                    if (!reader.TryRead(out var message)) continue;
                    // 默认重试3次（每次间隔1秒）
                    await Retry.Invoke(async () => await Activator.CreateInstance<MyChannelHandler>().InvokeAsync(message), 3, 1000, finalThrow: false);
                }
            }, TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// CallContext方式
        /// 了解更多 AsyncLocal<T> 知识：https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0
        /// </summary>
        public void CallContextDemo()
        {
            CallContext.SetLocalValue("name", "Furion");
            CallContext.GetLocalValue("name");

            CallContext<int>.SetLocalValue("count", 1);
            CallContext<int>.GetLocalValue("count");
        }
    }
}
